﻿using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using MongoDB.Bson;
using MongoDB.Driver;
using SDCloudSolution.SDCloud.DataLayer.ModelData.Interfaces;
using SDCloudSolution.SDCloud.DataLayer.MongoDb;
using SDCloudSolution.SDCloud.DataLayer.MongoDb.Interfaces;
using SDCloudSolution.SDCloud.Entities.Models.Data;
using SDCloudSolution.SDCloud.Entities.Models;

namespace SDCloudSolution.SDCloud.DataLayer.ModelData
{
    public class MongoModelMetadataDataProvider : BaseMongoDataProvider
    {
        public MongoModelMetadataDataProvider(ISdcloudMongoClient client, ISdCloudMongoDbSettingsProvider settings)
            : base(client, settings.ModelResultDataBaseName)
        {
            
        }

        protected IMongoCollection<BsonDocument> GetCollection()
        {
            return GetDatabase().GetCollection<BsonDocument>("modelMetadata");
        }

        public async Task<ModelMetadataEntity> GetMetadataByModelIdAsync(int modelId)
        {
            var result = await GetModelMetadata(modelId);
            

            return result;
        }

        private async Task<ModelMetadataEntity> GetModelMetadata(int modelId)
        {
            var filter = GetFilterByModelId(modelId);

            var documents = await GetCollection().Find(filter).Limit(1).ToListAsync();

            return (ModelMetadataEntity)MongoDbConverter.ToObjectFromBsonDocument(documents.FirstOrDefault(),
                typeof(ModelMetadataEntity));
        }

        public async Task InsertAsync(ModelMetadataEntity modelMetadata)
        {            
            ModelMetadataEntity existingEntity = await GetModelMetadata(modelMetadata.ModelId);

            Task modelResultInsertionTask;
            if (null != existingEntity)
            {
                /* If we already have metadata for this model */
                /*  we will update it */
                modelResultInsertionTask =
                    GetCollection().ReplaceOneAsync(
                        GetFilterByModelId(modelMetadata.ModelId),
                        MongoDbConverter.ToBsonDocumentByAttributes(modelMetadata)
                    );
            }
            else
            {
                /* If we don't have metadata for this model */
                /*  we will insert new entity */
                modelResultInsertionTask =
                    GetCollection().InsertOneAsync(
                        MongoDbConverter.ToBsonDocumentByAttributes(modelMetadata)
                    );
            }

        }

        public Task DeleteAsync(int modelId)
        {
            return Task.WhenAll(GetCollection().DeleteOneAsync(
                                        GetFilterByModelId(modelId)
                                    )
                               );
        }

        private FilterDefinition<BsonDocument> GetFilterByModelId(int modelId)
        {
            return Builders<BsonDocument>.Filter.Eq(
                ModelMetadataEntity.Fields.MODEL_ID, modelId
            );
        }
    }
}
